package com.flyduck.service.impl;

import com.flyduck.domain.*;
import com.flyduck.mapper.SysMenuMapper;
import com.flyduck.mapper.SysRoleMapper;
import com.flyduck.service.SysMenuService;
import com.flyduck.vo.QueryVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: flyduck-admin
 * @description:
 * @author: flyduck
 * @create: 2020-05-09 10:04
 **/
@Transactional
@Service
public class SysMenuServiceImpl implements SysMenuService {

    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;



    /**
     * 首页数据
     * @param queryVo
     * @return
     */
    @Override
    public Set<SysMenu> findTree(QueryVo queryVo) {
        //条件查询
         List<SysMenu> sysMenuList = sysMenuMapper.findList(queryVo.getKeyword());
        //构建树
        return buildTree(sysMenuList);
    }

    /**
     * 前端菜单
     * @return
     */
    @Override
    public Set<SysMenu> build() {
        Subject subject = SecurityUtils.getSubject();
        SysUser sysUser = (SysUser) subject.getPrincipal();
        List<SysMenu> sysMenuList = new ArrayList<>();
        if(sysUser.getAdmin()){
             sysMenuList = sysMenuMapper.findList("");
        }else {
            //条件查询
             sysMenuList = sysMenuMapper.getMenusByUserId(sysUser.getId());
        }
        sysMenuList = sysMenuList.stream().filter(sysMenu -> sysMenu.getType() != 2).collect(Collectors.toList());
        //构建树
        return buildTree(sysMenuList);
    }

    /**
     * 保存菜单
     * @param sysMenu
     */
    @Override
    public void save(SysMenu sysMenu) {
        sysMenuMapper.insertSelective(sysMenu);
    }

    /**
     * 更新菜单
     * @param sysMenu
     */
    @Override
    public void update(SysMenu sysMenu) {
        sysMenuMapper.updateByPrimaryKeySelective(sysMenu);
    }

    /**
     * 根据菜单id删除当前及以下的所有菜单
     * @param id
     */
    @Override
    public void deleteById(Long id) {
       //根据id获取当前节点以下的所有节点的id集合
        Set<Long> childNodeIds = findNextNodeIds(id);
        childNodeIds.add(id);
        for (Long childNodeId : childNodeIds) {
            sysMenuMapper.deleteByPrimaryKey(childNodeId);
        }
    }

    /**
     * 根据菜单id查询菜单
     * @param id
     * @return
     */
    @Override
    public SysMenu getMenuById(Long id) {
        return sysMenuMapper.getMenuById(id);
    }

    /**
     * 根据用户id查询所有的菜单(去重)
     * @param userId
     * @return
     */
    @Override
    public List<SysMenu> getMenusByUserId(Long userId) {
        return  sysMenuMapper.getMenusByUserId(userId);
    }


    //把当前的下一级的节点返回，然后循环调用这个方法，把循环调用这个方法的id集合也加进去
    private Set<Long> findNextNodeIds(Long pid) {
        Set<Long> childNodeIds = new HashSet<>();
        //子节点
        List<SysMenu> childNodes = sysMenuMapper.findAllByPid(pid);
        for (SysMenu childNode : childNodes) {
            childNodeIds.add(childNode.getId());
            Set<Long> nextNodeIds = findNextNodeIds(childNode.getId());
            childNodeIds.addAll(nextNodeIds);
        }

        return childNodeIds;
    }


    //构建树
    private Set<SysMenu> buildTree(List<SysMenu> sysMenuList) {
        Set<SysMenu> trees = new LinkedHashSet<>();
        Set<SysMenu> menus = new LinkedHashSet<>();
        List<Long> menuIds = sysMenuList.stream().map(SysMenu::getId).collect(Collectors.toList());
        boolean isChild;
        for (SysMenu sysMenu : sysMenuList) {
            isChild = false;
            if(sysMenu.getPid() == 0){
                trees.add(sysMenu);
            }
            for (SysMenu menu : sysMenuList) {
              if(menu.getPid().equals(sysMenu.getId())){
                  isChild = true;
                  if(sysMenu.getChildren() == null){
                      sysMenu.setChildren(new ArrayList<>());
                  }
                  sysMenu.getChildren().add(menu);
                  sysMenu.getChildren().sort((o1, o2) -> o1.getSort().compareTo(o2.getSort()));
              }
            }
            if(isChild){
                menus.add(sysMenu);
            }else if(!menuIds.contains(sysMenu.getPid())){
                menus.add(sysMenu);
            }
        }
        if(CollectionUtils.isEmpty(trees)){
            trees = menus;
        }
        return trees;
    }
}
